#include <iostream>
#include "XMLWriter.h"
#include "XMLString.h"


using namespace xercesc;
using namespace std;


/**
 * Constructor
 * All members set to NULL and Xerces platform initialized
 */
XMLWriter::XMLWriter()
{
	m_doc = NULL;
	m_prodElem = NULL;
	m_impl = NULL;
	m_rootElem = NULL;

	try
	{
		XMLPlatformUtils::Initialize();
	}
	catch( XMLException& e )
	{
		char* message = XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit initialization error: " << message << endl;
		XMLString::release( &message );
	}
}


/**
 * Destructor
 * Xerces platform is uninitialized
 * TODO delete members always crashes. Have to sort it out.
 */
XMLWriter::~XMLWriter()
{
	try
	{
		XMLPlatformUtils::Terminate();
		
	}
	catch( xercesc::XMLException& e )
	{
		char* message = xercesc::XMLString::transcode( e.getMessage() );
		cerr << "XML toolkit teardown error: " << message << endl;
		XMLString::release( &message );
	}
}


/**
 * Initialize Xerces configuration
 * @param char* strRoot - Name of Root element
 * @param char* strAppSettings - Name of 1st Element
 * @return void
 */
void XMLWriter::init(char* strRoot, char* strAppSettings)
{
	m_impl =  DOMImplementationRegistry::getDOMImplementation(L"LS");
	m_doc = m_impl->createDocument(0, X(strRoot), 0); 
	m_rootElem = m_doc->getDocumentElement();
	m_prodElem = m_doc->createElement(X(strAppSettings));
	m_rootElem->appendChild(m_prodElem);
}


/**
 * Adds attributes and its value to 1st element
 * @param const char* name - name of attribute
 * @param const char* value - value of attribute
 * @return void
 */
void XMLWriter::addAttribute(const char* name, const char* value)
{
	if (m_prodElem != NULL)
	{
		m_prodElem->setAttribute(X(name), X(value));
	}
}
	

/**
 * Return the first registered implementation that has the desired features. In this case, we are after a DOM implementation that has the LS feature... or Load/Save.
 * Create a DOMLSSerializer which is used to serialize a DOM tree into an XML document.
 * Make the output more human readable by inserting line feeds.
 * The end-of-line sequence of characters to be used in the XML being written out. 
 * Specify the target for the XML output.
 * Create a new empty output destination object.
 * Set the stream to our target.
 * Write the serialized output to the destination.
 * Cleanup.
 * @param const char * filePath - name of file to save to
 * @return void
 */
void XMLWriter::writeToFile(const char * filePath)
{
	DOMLSSerializer *serializer = NULL;
	XMLFormatTarget *formatTarget = NULL;
	DOMLSOutput *output = NULL;
	
	serializer = ((DOMImplementationLS*)m_impl)->createLSSerializer();
	if (serializer->getDomConfig()->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
		serializer->getDomConfig()->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
	serializer->setNewLine(XMLString::transcode("\r\n")); 
	formatTarget = new LocalFileFormatTarget(X(filePath));
	output = ((DOMImplementationLS*)m_impl)->createLSOutput();
	output->setByteStream(formatTarget);
	serializer->write(m_doc, output);
	serializer->release();
	delete formatTarget;
	output->release();
}

